﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Drawing;
using System.Threading;
using System.Runtime.InteropServices;

using DNA;

using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using TJADRICD.CollaborativeDesignPlugin.Function;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.ApplicationServices;
using DBTransMan = Autodesk.AutoCAD.DatabaseServices.TransactionManager;
using Application = Autodesk.AutoCAD.ApplicationServices.Application;

namespace TJADRICD.CollaborativeDesignPlugin
{
    class CommandSplit
    {

        #region JitLotH`s Code
        public void DeleteXRef(Database db, Transaction ta)
        {
            BlockTable bt = (BlockTable)ta.GetObject(db.BlockTableId, OpenMode.ForRead);
            BlockTableRecord btr = (BlockTableRecord)ta.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

            foreach (ObjectId objectid in btr)
            {
                Entity ent = (Entity)ta.GetObject(objectid, OpenMode.ForWrite);
                if (ent is BlockReference)  //Whether the entity is a block reference
                {
                    BlockReference bref = ent as BlockReference;
                    BlockTableRecord btr2 = (BlockTableRecord)ta.GetObject(bref.BlockTableRecord, OpenMode.ForRead);
                    if (btr2.IsFromExternalReference)  //Whether the block reference is external
                    {
                        ent.Erase();
                    }
                }
            }
        }

        [CommandMethod("deletexref")]
        public void deletexref()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor edt = doc.Editor;
            Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = db.TransactionManager;

            using (Transaction ta = tm.StartTransaction())
            {
                DeleteXRef(db, ta);  //Call function to delete external references

                ta.Commit();
            }
        }

        static public string GetMajor(BlockReference blockRef)
        {
            string DisciplineEnglish = "";
            Database db = Tools.Database;
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                AttributeCollection blockRefAttrs = blockRef.AttributeCollection;
                foreach (ObjectId attrRefId in blockRefAttrs)
                {
                    AttributeReference attrRef = (AttributeReference)trans.GetObject(attrRefId, OpenMode.ForRead);
                    if (attrRef.Tag == "DisciplineChinese")
                    {
                        string temp = attrRef.TextString;
                        switch (temp)
                        {
                            case "强电":
                                DisciplineEnglish = "QD";
                                break;
                            case "弱电":
                                DisciplineEnglish = "RD";
                                break;
                            case "建筑":
                                DisciplineEnglish = "JZ";
                                break;
                            case "结构":
                                DisciplineEnglish = "JG";
                                break;
                            case "给排水":
                                DisciplineEnglish = "GPS";
                                break;
                            case "暖通":
                                DisciplineEnglish = "NT";
                                break;
                            case "动力":
                                DisciplineEnglish = "DL";
                                break;
                        }
                    }
                }
            }
            return DisciplineEnglish;
        }

        static public string GetFileNameFromFrame(BlockReference blockRef)
        {
            string fileName = "";
            //项目编号-子项编号-专业-阶段-图号-版次.dwg
            string ProjectNo = "";
            string SubProjectNo = "";
            string DisciplineChinese = "";
            string StageChinese = "";
            string SheetNo = "";
            string Rev = "";
            Database db = Tools.Database;
            VersionList vi = new VersionList();
            using(Transaction trans = db.TransactionManager.StartTransaction())
            {
                AttributeCollection blockRefAttrs = blockRef.AttributeCollection;
                List<AttributeReference> attribute = new List<AttributeReference>();
                foreach (ObjectId attrRefId in blockRefAttrs)
                {
                    AttributeReference attrRef = (AttributeReference)trans.GetObject(attrRefId, OpenMode.ForRead);
                    attribute.Add(attrRef);
                    if(attrRef.Tag=="ProjectNo")
                    {
                        ProjectNo = attrRef.TextString;
                    }
                    if (attrRef.Tag == "SubProjectNo")
                    {
                        SubProjectNo = attrRef.TextString;
                    }
                    if (attrRef.Tag == "DisciplineChinese")
                    {
                        DisciplineChinese = attrRef.TextString;
                    }
                    if (attrRef.Tag == "StageChinese")
                    {
                        StageChinese = attrRef.TextString;
                    }
                    if (attrRef.Tag == "SheetNo")
                    {
                        SheetNo = attrRef.TextString;
                    }
                    if (attrRef.Tag == "Rev")
                    {
                        Rev = attrRef.TextString;
                    }
                }
                vi.LoadFromAttribute(attribute);
            }
            //项目编号-子项编号-专业-阶段-图号-版次.dwg
            fileName = ProjectNo + "-"
                        + SubProjectNo + "-"
                        + DisciplineChinese + "-"
                        + StageChinese + "-"
                        + SheetNo + "-"
                        + (char)(vi.versionList.Count - 1 + 'A')
                        + ".dwg";

            return fileName;
        }

        [CommandMethod("splitall")]
        public void splitall()
        {
            Database dbSource = Application.DocumentManager.MdiActiveDocument.Database;
            List<BlockReference> listRefs = new List<BlockReference>();
            List<Entity> listEntForCheck = new List<Entity>();

            using (Transaction taForGetObj = dbSource.TransactionManager.StartTransaction())
            {
                BlockTable btSource = taForGetObj.GetObject(dbSource.BlockTableId, OpenMode.ForRead) as BlockTable;
                BlockTableRecord btrSource = taForGetObj.GetObject(btSource[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
                
                foreach (ObjectId idObj in btrSource)
                {
                    Entity entTarget = taForGetObj.GetObject(idObj, OpenMode.ForWrite) as Entity;
                    listEntForCheck.Add(entTarget);

                    if (entTarget is BlockReference)
                    {
                        BlockReference brTarget = entTarget as BlockReference;
                        BlockTableRecord btrTarget = taForGetObj.GetObject(brTarget.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;

                        if (!btrTarget.IsFromExternalReference && CommandFrame.IsVersionType(btrTarget.Name))
                        {
                            listRefs.Add(brTarget);
                        }
                    }
                }

                int nSum = listRefs.Count * listEntForCheck.Count;
                int nTimeNeed = (int)((double)16 / (double)143000 * (double)nSum);

                int iCount = 0;
                foreach (BlockReference brSplitTarget in listRefs)
                {
                    int nTimeLeft = nTimeNeed * (listRefs.Count - iCount) / listRefs.Count;
                    Tools.WriteMessageWithReturn("距离工作完成还剩" +nTimeLeft.ToString() + "秒");
                    ++iCount;
                    string strNewFileName = GetFileNameFromFrame(brSplitTarget);
                    string major = GetMajor(brSplitTarget);
                    Tools.WriteMessageWithReturn("Spliting File No." + iCount.ToString());

                    using (Transaction taForSplit = dbSource.TransactionManager.StartTransaction())
                    {
                        BlockTable btFoSplit = taForSplit.GetObject(dbSource.BlockTableId, OpenMode.ForRead) as BlockTable;
                        BlockTableRecord btrForSplit = taForSplit.GetObject(btFoSplit[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
                        Extents3d ext3dSplitTarget = brSplitTarget.GeometricExtents;

                        foreach (Entity entForCheck in listEntForCheck)
                        {
                            try
                            {
                                Extents3d ext3dEntityForCheck = entForCheck.GeometricExtents;
                                if (ext3dEntityForCheck.MaxPoint.X > ext3dSplitTarget.MaxPoint.X || ext3dEntityForCheck.MaxPoint.Y > ext3dSplitTarget.MaxPoint.Y
                                 || ext3dEntityForCheck.MinPoint.X < ext3dSplitTarget.MinPoint.X || ext3dEntityForCheck.MinPoint.Y < ext3dSplitTarget.MinPoint.Y)
                                    entForCheck.Erase();
                                else if (entForCheck is BlockReference)
                                {
                                    BlockReference brForCheck = entForCheck as BlockReference;
                                    BlockTableRecord btrForCheck = taForSplit.GetObject(brForCheck.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;

                                    if (btrForCheck.IsFromExternalReference)
                                    {
                                        ObjectId blkNewId = btrForCheck.ObjectId;
                                        try
                                        {
                                            Database dbXRef = new Database(false, true);
                                            dbXRef.ReadDwgFile(btrForCheck.PathName, FileShare.ReadWrite, true, "");
                                            blkNewId = dbSource.Insert(btrForCheck.Name + "_Rec", dbXRef, false);

                                            Point3dCollection pts = new Point3dCollection();
                                            entForCheck.GetStretchPoints(pts);
                                            BlockReference br2 = new BlockReference(pts[0], blkNewId);
                                            br2.ScaleFactors = brForCheck.ScaleFactors;
                                            btrForSplit.AppendEntity(br2);
                                            taForSplit.AddNewlyCreatedDBObject(br2, true);
                                            entForCheck.Erase();
                                        }
                                        catch
                                        {
                                            //Tools.WriteMessageWithReturn(ex.ToString());
                                        }
                                    }
                                }
                            }
                            catch
                            {
                                //Tools.WriteMessageWithReturn(ex.ToString());
                            }
                        }
                        string path = null;
                        path = GetSubProPath(dbSource.Filename) + "Common\\TZ\\" + major + '\\';
                        DirectoryInfo dic = new DirectoryInfo(path);
                        if (!dic.Exists)
                        {
                            MessageBox.Show("目录：" + path + "不存在！");
                            continue;
                        }
                        path = path + strNewFileName;
                        if (!string.IsNullOrEmpty(path))
                        {
                          //  MessageBox.Show(path);
                            dbSource.SaveAs(path, DwgVersion.Current);
                            Tools.WriteMessageWithReturn("已将子图保存至" + strNewFileName);
                            //CommandSign.PublishFile(path);
                        }
                    }
                }
            }
            Tools.WriteMessageWithReturn("Done!");
        }

        [CommandMethod("splitsingle")]
        public void splitsingle()
        {
            List<String> list = new List<String>();
            Editor edGetRef = Tools.Editor;
            ObjectId idRef;

            while (true)
            {
                PromptEntityResult perResult = edGetRef.GetEntity("请选择要分裂的图框");
                if (perResult.Status != PromptStatus.OK)
                {
                    return;
                }
                idRef = perResult.ObjectId;
                if (Tools.GetEntity(idRef).GetType() == typeof(BlockReference))
                {
                    Database dbSource = Application.DocumentManager.MdiActiveDocument.Database;
                    SplitForSingle(dbSource, idRef);
                }
            }
        }


        [CommandMethod("try123")]
        public static void try123()
        {
            Editor edGetRef = Tools.Editor;
            ObjectId idRef;

            while (true)
            {
                PromptEntityResult perResult = edGetRef.GetEntity("请选择要分裂的图框");
                if (perResult.Status != PromptStatus.OK)
                {
                    return;
                }

                idRef = perResult.ObjectId;
                if (Tools.GetEntity(idRef).GetType() == typeof(BlockReference))
                {
                    break;
                }
            }

            Database dbSource = Application.DocumentManager.MdiActiveDocument.Database;
            using (Transaction taForSplit = dbSource.TransactionManager.StartTransaction())
            {
                BlockReference brTarget = taForSplit.GetObject(idRef, OpenMode.ForRead) as BlockReference;
                Extents3d ext3dTarget = brTarget.GeometricExtents;


                Tools.WriteMessageWithReturn(ext3dTarget.MaxPoint.X.ToString());
                Tools.WriteMessageWithReturn(ext3dTarget.MaxPoint.Y.ToString());
                Tools.WriteMessageWithReturn(ext3dTarget.MinPoint.X.ToString());
                Tools.WriteMessageWithReturn(ext3dTarget.MinPoint.Y.ToString());
            }

        }

        public static string GetSubProPath(string filePath)
        {
            FileInfo fi = new FileInfo(filePath);
            DirectoryInfo di = fi.Directory;

            if (di == null)
            {
                return String.Empty;
            }
            DirectoryInfo di2 = new DirectoryInfo(di.FullName + @"\Common\");
            while (!di2.Exists)
            {
                if (di == null)
                {
                    return String.Empty;
                }
                di = di.Parent;
                if (di == null)
                {
                    return String.Empty;
                }
                di2 = new DirectoryInfo(di.FullName + @"\Common\");

            }
            return di.FullName+@"\";
        }

        public static void SplitForSingle(Database dbSource, ObjectId idRef)
        {
            using (Transaction taForSplit = dbSource.TransactionManager.StartTransaction())
            {
                BlockReference brTarget = taForSplit.GetObject(idRef, OpenMode.ForRead) as BlockReference;
                Extents3d ext3dTarget = brTarget.GeometricExtents;

                string strNewFileName = GetFileNameFromFrame(brTarget);
                string major = GetMajor(brTarget);

                BlockTable btSource = taForSplit.GetObject(dbSource.BlockTableId, OpenMode.ForRead) as BlockTable;
                BlockTableRecord btrSource = taForSplit.GetObject(btSource[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;

                foreach (ObjectId idForCheck in btrSource)
                {
                    Entity entForCheck = taForSplit.GetObject(idForCheck, OpenMode.ForWrite) as Entity;

                    try
                    {
                        Extents3d ext3dForCheck = entForCheck.GeometricExtents;
                        if (ext3dForCheck.MaxPoint.X > ext3dTarget.MaxPoint.X || ext3dForCheck.MaxPoint.Y > ext3dTarget.MaxPoint.Y
                         || ext3dForCheck.MinPoint.X < ext3dTarget.MinPoint.X || ext3dForCheck.MinPoint.Y < ext3dTarget.MinPoint.Y)
                            entForCheck.Erase();
                        else if (entForCheck is BlockReference)
                        {
                            BlockReference brRef = entForCheck as BlockReference;
                            BlockTableRecord btrRef = taForSplit.GetObject(brRef.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;

                            if (btrRef.IsFromExternalReference)
                            {
                                try
                                {
                                    Database dbXRef = new Database(false, true);
                                    dbXRef.ReadDwgFile(btrRef.PathName, FileShare.Read, true, "");
                                    ObjectId idNewBTR = dbSource.Insert(btrRef.Name + "_Rec", dbXRef, false);

                                    Point3dCollection pts = new Point3dCollection();
                                    entForCheck.GetStretchPoints(pts);
                                    BlockReference brNew = new BlockReference(pts[0], idNewBTR);
                                    brNew.ScaleFactors = brRef.ScaleFactors;
                                    btrSource.AppendEntity(brNew);
                                    taForSplit.AddNewlyCreatedDBObject(brNew, true);
                                    entForCheck.Erase();
                                }
                                catch
                                {
                                }
                            }
                        }
                    }
                    catch
                    {
                    }
                }
                string path = null;
                path = GetSubProPath(dbSource.Filename) + "Common\\TZ\\" + major + '\\';
                DirectoryInfo dic = new DirectoryInfo(path);
                if (!dic.Exists)
                {
                    MessageBox.Show("目录：" + path + "不存在！");
                    return;
                }
                path = path + strNewFileName;
                if (!string.IsNullOrEmpty(path))
                {
                    dbSource.SaveAs(path, DwgVersion.Current);
                    Tools.WriteMessageWithReturn("已将子图保存至" + strNewFileName);
/*                    list.Add(path);*/

                }
            }
        }
        
        #endregion
    }
}
